package com.qf.bank.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.qf.bank.common.Const;
import com.qf.bank.entity.Account;
import com.qf.bank.response.R;
import com.qf.bank.response.RCodes;
import com.qf.bank.utils.TokenUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author YaoJiXing
 */
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 在有请求发起访问获取数据的时候触发这个方法
     *
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setContentType("application/json;charset=utf-8");

        // 如果请求方式是 OPTIONS 就代表预处理（预检请求）由浏览器发送
        if (request.getMethod().equals("OPTIONS")) {
            //直接放行
            return true;
        }

        // String jwt = request.getParameter("jwt");
        // 获取保存在头信息中的 token
        String jwt = request.getHeader(Const.AUTHORIZATION);
        R r = null;

        try {
            Claims c = TokenUtils.getTokenValue(jwt);

            String str = stringRedisTemplate.boundValueOps("token_" + jwt).get();
            Account account = new ObjectMapper().readValue(str, Account.class);

            Map<String, Object> data = (Map<String, Object>) c.get("user");
            //通过Map取值
            String cardno = (String) data.get("cardno");

            //验证 Token 信息
            if (account.getCardno().equals(cardno)) {
                Long time = stringRedisTemplate.getExpire("token_" + jwt);
                Long endTime = 60 * 3L;
                if (time < endTime) {
                    stringRedisTemplate.expire("token_" + jwt, 4, TimeUnit.MINUTES);
                }
            }

        } catch (ExpiredJwtException e) { //令牌过期
            r = R.createFAIL(RCodes.NOT_LOGIN.getCode(), "登录已过期，请重新登录");
        } catch (MalformedJwtException e) { //错误令牌
            r = R.createFAIL(RCodes.NOT_LOGIN.getCode(), "登录信息有误，请重新登录");
        } catch (SignatureException e) { //签名错误
            r = R.createFAIL(RCodes.NOT_LOGIN.getCode(), "登录信息有误，请重新登录");
        } catch (IllegalArgumentException e) { //非法参数
            r = R.createFAIL(RCodes.NOT_LOGIN.getCode(), "登录信息有误，请重新登录");
        }

        if (r != null) {
            ObjectMapper obj = new ObjectMapper();
            //把 R 转为 JSON
            String jsonString = obj.writeValueAsString(r);
            response.getWriter().println(jsonString);
            //r不为空，证明出现了异常
            return false;
        }
        return true;
    }

}